-- Copyright 2008 Steven Barth <steven@midlink.org>
-- Copyright 2010-2012 Jo-Philipp Wich <jow@openwrt.org>
-- Licensed to the public under the Apache License 2.0.

local sys = require "luci.sys"
local utl = require "luci.util"
local dsp = require "luci.dispatcher"
local nxo = require "nixio"

local ft = require "luci.tools.firewall"
local nw = require "luci.model.network"
local uci = require "luci.model.uci".cursor()
local m, s, o, k, v

arg[1] = arg[1] or ""

local isnew = false

if arg[1] == "new" then
	isnew = true
	m = SimpleForm("snat_edit", translate("Firewall - SNAT Rules"),
	translate("This page can change or create a SNAT rule that matches the source address of the rule traffic to be rewritten to specify the IP address."))
	m.anonymous = true
	m.addremove = false
	m.title = "%s > %s SNAT" %{ translate("Firewall - SNAT Rules"), translate("Add") }
else
	m = Map("firewall",
		translate("Firewall - SNAT Rules"),
		translate("This page can change or create a SNAT rule that matches the source address of the rule traffic to be rewritten to specify the IP address."))

end

m.redirect = dsp.build_url("admin/network/firewall/snat")

nw.init(m.uci)

local rule_type = ""
local wan_zone = nil
-- 不是新建,也不是redirect下的SNAT，则返回
if isnew then

	rule_type = "redirect"
	s = m:section(SimpleSection)
	
else

	rule_type = m.uci:get("firewall", arg[1])
	if rule_type == "redirect" and m:get(arg[1], "target") ~= "SNAT" then
		rule_type = nil
	end
	if not rule_type then
		luci.http.redirect(m.redirect)
		return
	end

	s = m:section(NamedSection, arg[1], "redirect", "")

	m.uci:foreach("firewall", "zone",
	function(s)
		local n = s.network or s.name
		if n then
			local i
			for i in utl.imatch(n) do
				if i == "wan" then
					wan_zone = s.name
					return false
				end
			end
		end
	end)
end

s.anonymous = true
s.addremove = false


local name = m:get(arg[1], "name") or m:get(arg[1], "_name")
if not name or #name == 0 then
	name = translate("(Unnamed SNAT)")
else
	name = "SNAT %s" % name
end

m.title = "%s - %s" %{ translate("Firewall - SNAT Rules"), name }


ft.opt_enabled(s, Button)
ft.opt_name(s, Value, translate("Name"))


o = s:option(Value, "proto",
	translate("Protocol"),
	translate("You may specify multiple by selecting \"-- custom --\" and \
	           then entering protocols separated by space."))

o:value("all", "All protocols")
o:value("tcp udp", "TCP+UDP")
o:value("tcp", "TCP")
o:value("udp", "UDP")
o:value("icmp", "ICMP")
o.default = "all"

function o.cfgvalue(...)
	local v = Value.cfgvalue(...)
	if not v or v == "tcpudp" then
		return "tcp udp"
	end
	return v
end


o = s:option(Value, "src", translate("Source zone"))
o.nocreate = true
o.default = "lan"
o.template = "cbi/firewall_zonelist"


o = s:option(Value, "src_ip", translate("Source IP address"))
o.rmempty = true
o.datatype = "neg(ipaddr)"
o.placeholder = translate("any")

luci.sys.net.ipv4_hints(function(ip, name)
	o:value(ip, "%s (%s)" %{ ip, name })
end)


o = s:option(Value, "src_port",
	translate("Source port"),
	translate("Match incoming traffic originating from the given source \
		port or port range on the client host."))
o.rmempty = true
o.datatype = "neg(portrange)"
o.placeholder = translate("any")


o = s:option(Value, "dest", translate("Destination zone"))
o.nocreate = true
o.default = "wan"
o.template = "cbi/firewall_zonelist"


o = s:option(Value, "dest_ip", translate("Destination IP address"))
o.datatype = "neg(ip4addr)"

luci.sys.net.ipv4_hints(function(ip, name)
	o:value(ip, "%s (%s)" %{ ip, name })
end)


o = s:option(Value, "dest_port",
	translate("Destination port"),
	translate("Match forwarded traffic to the given destination port or \
		port range."))

o.rmempty = true
o.placeholder = translate("any")
o.datatype = "neg(portrange)"


o = s:option(Value, "src_dip",
	translate("SNAT IP address"),
	translate("Rewrite matched traffic to the given address."))
o.rmempty = false
o.datatype = "ip4addr"

for k, v in ipairs(nw:get_interfaces()) do
	local a
	for k, a in ipairs(v:ipaddrs()) do
		o:value(a:host():string(), '%s (%s)' %{
			a:host():string(), v:shortname()
		})
	end
end

-- 暂时去掉端口部分
-- o = s:option(Value, "src_dport", translate("SNAT port"),
-- 	translate("Rewrite matched traffic to the given source port. May be \
-- 		left empty to only rewrite the IP address."))
-- o.datatype = "portrange"
-- o.rmempty = true
-- o.placeholder = translate('Do not rewrite')


if isnew then

	function m.handle(self, state, data)
		if state == FORM_VALID then
			
			
			uci:section("firewall", "redirect", nil, {
				target = "SNAT",
				src = data.src,
				dest = data.dest,
				name = data.name,
				src_dport = data.src_dport,
				src_dip = data.src_dip,
				src_port = data.src_port,
				src_ip = data.src_ip,
				dest_port = data.dest_port,
				dest_ip = data.dest_ip,
				enabled = data.enabled,
				proto = data.proto,

			})
			uci:save("firewall")
			luci.http.redirect(m.redirect)
		end
		return true
	end
end

return m

